package com.um.jdy.app.activity.manager;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.um.jdy.app.activity.entity.dto.FullReduceGoodsPageDTO;
import com.um.jdy.app.activity.entity.dto.GroupGoodsPageDTO;
import com.um.jdy.app.activity.entity.dto.SeckillGoodsDTO;
import com.um.jdy.app.activity.entity.vo.*;
import com.um.jdy.common.activity.code.ActivityCode;
import com.um.jdy.common.activity.entity.po.Coupons;
import com.um.jdy.common.activity.service.CouponsService;
import com.um.jdy.common.market.entity.po.Activity;
import com.um.jdy.common.market.entity.po.FullReduce;
import com.um.jdy.common.market.entity.po.Group;
import com.um.jdy.common.market.entity.po.SeckillTimes;
import com.um.jdy.common.market.entity.vo.ActivityVO;
import com.um.jdy.common.market.entity.vo.FullReduceVO;
import com.um.jdy.common.market.service.ActivityService;
import com.um.jdy.common.market.service.FullReduceService;
import com.um.jdy.common.market.service.GroupService;
import com.um.jdy.common.market.service.SeckillTimesService;
import com.um.jdy.common.member.service.MemberUserService;
import com.um.jdy.common.shop.code.ShopGoodsCode;
import com.um.jdy.common.shop.entity.vo.GoodsVO;
import com.um.jdy.common.shop.enums.ActivityEnum;
import com.um.jdy.common.shop.enums.CouponsEnum;
import com.um.jdy.common.shop.enums.OrderEnum;
import com.um.jdy.common.shop.service.GoodsService;
import com.um.springboot.starter.entity.Page;
import com.um.springboot.starter.exception.ServiceException;
import com.um.springboot.starter.utils.StringUtil;
import com.um.springboot.starter.utils.condition.ConditionBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @Title
 * @Description
 * @Author renjunwei
 * @Date 2023/5/22 10:37
 */
@Slf4j
@Service
public class ActivityManager {

    @Autowired
    ActivityService activityService;

    @Autowired
    GroupService groupService;

    @Autowired
    GoodsService goodsService;

    @Autowired
    MemberUserService userService;

    @Autowired
    SeckillTimesService seckillTimesService;

    @Autowired
    FullReduceService fullReduceService;

    @Autowired
    CouponsService couponsService;

    /**
     * 分页查询满减活动商品
     *
     * @param dto
     * @return
     */
    public Page<GroupGoodsItemVO> getGroupGoodsPage(GroupGoodsPageDTO dto) {
        Page<GroupGoodsItemVO> page = new Page(dto);

        Map<String, String> condition = ConditionBuilder.create()
                .putLike("g.shop_goods_name", dto.getShop_goods_name())
                .put("g.com_id",activityService.getComId())
                .putRightLike("g.code", dto.getCode())
                .build();

        return activityService.getCMSViewModelPageBySqlName(page, "get_group_goods_page", "get_group_goods_count",
                GroupGoodsItemVO.class, condition.keySet().toArray(new String[0]), condition.values().toArray(new String[0]),
                new ArrayList(), new String[]{}, new String[]{});
    }

    /**
     * 查询拼团活动商品列表
     *
     * @param goodsSize
     * @return
     */
    public List getGroupGoodsList(Integer goodsSize) {
        if(null == goodsSize || 0 == goodsSize){
            goodsSize = 10;
        }
        List list = activityService.getViewModelList("get_group_goods_list", GroupGoodsItemVO.class, new Object[]{activityService.getComId(),goodsSize});
        return list;
    }

    /**
     * 查询拼团详情
     *
     * @param marketGroupId
     * @return
     */
    public GroupDetailVO getGroup(String marketGroupId) {
        Group group = groupService.getEntity(marketGroupId);
        if(null == group){
            throw new ServiceException(ActivityCode.GroupNotExist);
        }
        ActivityGoodsOptionVO activityGoods = groupService.getViewModel("get_activity_goods_option",
                ActivityGoodsOptionVO.class, new Object[]{group.getMarketActivityGoodsId(), group.getMarketActivityGoodsOptionId(),group.getComId()});
        if(null == activityGoods){
            throw new ServiceException(ShopGoodsCode.GoodsNotExist);
        }
        activityGoods.setOrderNum(getActivityGoodsOrderNum(activityGoods.getMarketActivityGoodsId()));

        Activity activity = activityService.getEntity(activityGoods.getMarketActivityId());
        // if(null == activity || !this.validateActivityIsProcessing(activity)){
        //     throw new ServiceException(ActivityCode.ActivityExpired);
        // }

        List<GroupOrderItemVO> userList = activityService.getViewModelList("get_group_order_list", GroupOrderItemVO.class,
                new Object[]{group.getMarketGroupId(),group.getComId(), group.getShopOrderIds()});
        boolean isJoinGroup = false;
        for(GroupOrderItemVO user : userList){
            if(user.getMemberUserId().equals(userService.get().getMemberUserId())){
                isJoinGroup = true;
                break;
            }
        }
       // if(userList.size() >= group.getGroupNum() && !isJoinGroup){
       //     throw new ServiceException(ActivityCode.GroupStarted);
       // }

        GroupDetailVO detail = BeanUtil.toBean(group, GroupDetailVO.class);
        detail.setUsers(userList);
        detail.setIsJoinGroup(isJoinGroup);
        detail.setGoods(activityGoods);
        detail.setActivity(BeanUtil.toBean(activity, ActivityVO.class));

        return detail;
    }

    /**
     * 查询秒杀活动场次
     *
     * @return
     */
    public List<SeckillTimesVO> getSeckillTimesList() {
        List<SeckillTimesVO> list = new ArrayList();

        // 正在进行和未开始的秒杀场次
        List<Activity> seckillList = activityService.getListBySqlName("get_current_seckill",new Object[]{activityService.getComId()});
        for(Activity seckill : seckillList){
            List<SeckillTimes> timesList = seckillTimesService.getList(new String[]{"market_activity_id"},
                    new String[]{seckill.getMarketActivityId()}, new String[]{"start_time"}, new String[]{"asc"});
            for (SeckillTimes times : timesList) {
                String dayStr = DateUtil.format(seckill.getBeginDate(), DatePattern.NORM_DATE_PATTERN);
                times.setStartTime(dayStr + " " + times.getStartTime() + ":00");
                times.setEndTime(dayStr + " " + times.getEndTime() + ":00");
                // times.put("begin_date",seckill.get("begin_date"));
            }
            list.addAll(BeanUtil.copyToList(timesList, SeckillTimesVO.class));
            if(list.size() > 5){
                break;
            }
        }

        if(list.size() >= 5){
            return ListUtil.sub(list,0,5);
        }else{
            // 正在进行和未开始的秒杀场次不足5场，将已结束的秒杀场次补齐5场
            List<Activity> endedSeckillList = activityService.getListBySqlName("get_ended_seckill",new Object[]{activityService.getComId()});
            for(Activity seckill : endedSeckillList){
                List<SeckillTimes> timesList = seckillTimesService.getList(new String[]{"market_activity_id"},
                        new String[]{seckill.getMarketActivityId()}, new String[]{"start_time"}, new String[]{"asc"});
                for (SeckillTimes times : timesList) {
                    String dayStr = DateUtil.format(seckill.getBeginDate(), DatePattern.NORM_DATE_PATTERN);
                    times.setStartTime(dayStr + " " + times.getStartTime() + ":00");
                    times.setEndTime(dayStr + " " + times.getEndTime() + ":00");
                    // times.put("begin_date",seckill.get("begin_date"));
                }
                list.addAll(0,BeanUtil.copyToList(timesList, SeckillTimesVO.class));
                if(list.size() > 5){
                    break;
                }
            }
        }

        int start = list.size()-5 > 0 ? list.size()-5 : 0;
        return ListUtil.sub(list,start,list.size());
    }

    /**
     * 查询秒杀活动商品
     *
     * @param dto
     * @param limit
     * @return
     */
    public List<SeckillGoodsItemVO> getSeckillGoodsList(SeckillGoodsDTO dto, Integer limit) {
        return activityService.getViewModelList("get_seckill_goods_list", SeckillGoodsItemVO.class,
                new Object[]{activityService.getComId(),dto.getMarket_seckill_times_id(), StringUtil.getQueryParam(dto.getShop_goods_name()), limit});
    }

    /**
     * 分页查询满减活动商品
     *
     * @param dto
     * @return
     */
    public Page<FullReduceGoodsItemVO> getFullReduceGoodsPage(FullReduceGoodsPageDTO dto) {
        Page page = new Page(dto);

        page = activityService.getViewModelPageBySqlName(page,"get_full_reduce_goods_page",
                "get_full_reduce_goods_count", FullReduceGoodsItemVO.class,
                new String[]{activityService.getComId(),StringUtil.getQueryParam(dto.getShop_goods_name())});

        List<FullReduce> fullReduceList = fullReduceService.getListBySqlName("get_full_reduce_activity_list", new Object[]{activityService.getComId()});
        Map<String, List<FullReduce>> mapFullReduce = new Hashtable();
        for(FullReduce fullReduce : fullReduceList){
            if(!mapFullReduce.containsKey(fullReduce.getMarketActivityId())){
                mapFullReduce.put(fullReduce.getMarketActivityId(), new ArrayList());
            }

            List<FullReduce> subList = mapFullReduce.get(fullReduce.getMarketActivityId());
            subList.add(fullReduce);
        }

        List<FullReduceGoodsItemVO> listGoods = page.getResult();
        for(FullReduceGoodsItemVO goods : listGoods){
            if(mapFullReduce.containsKey(goods.getMarketActivityId())){
                goods.setActivities(BeanUtil.copyToList(mapFullReduce.get(goods.getMarketActivityId()), FullReduceVO.class));
            }else{
                goods.setActivities(new ArrayList());
            }
        }

        return page;
    }

    /**
     * 验证活动是否进行中
     *
     * @param activity
     * @return
     */
    public boolean validateActivityIsProcessing(Activity activity) {
        if(null == activity){
            return false;
        }
        DateTime now = DateUtil.date();
        return DateUtil.compare(now, activity.getBeginDate()) > 0 &&
                DateUtil.compare(DateUtil.endOfDay(activity.getEndDate()), now) > 0;
    }

    /**
     * 查询活动商品销量
     * @param marketActivityGoodsId
     * @return
     */
    private Integer getActivityGoodsOrderUser(String marketActivityGoodsId){
        return activityService.getObjectBySqlName("get_goods_activity_order_user", new String[]{marketActivityGoodsId,activityService.getComId()},
                Integer.class);
    }

    /**
     * 查询活动商品销量
     * @param marketActivityGoodsId
     * @return
     */
    private Integer getActivityGoodsOrderNum(String marketActivityGoodsId){
        return activityService.getObjectBySqlName("get_goods_activity_order_num", new String[]{marketActivityGoodsId,activityService.getComId()},
                Integer.class);
    }

    /**
     * 查询满减赠品数量
     * @param marketActivityId
     * @param shopGoodsId
     * @return
     */
    private Integer getGoodsFullReduceGiftNum(String marketActivityId, String shopGoodsId){
        return activityService.getObjectBySqlName("get_goods_full_reduce_gift_num",
                new String[]{marketActivityId, shopGoodsId,activityService.getComId()},
                Integer.class);
    }


    /**
     * 查询商品所在的活动
     *
     * @param mallGoodsId
     * @return
     */
    public GoodsActivityVO getActivityByGoods(String mallGoodsId) {
        GoodsActivityVO activity = activityService.getViewModel("get_activity_by_goods_id", GoodsActivityVO.class,
                new Object[]{mallGoodsId,activityService.getComId(),mallGoodsId,activityService.getComId()});

        if (null == activity){
            return null;
        }

        //满减没有活动价，只有参与活动的商品
        if(ActivityEnum.Type.Reduce.name().equals(activity.getType())){
            List<FullReduce> fullReduceList = fullReduceService.getList("market_activity_id", activity.getMarketActivityId());
            List<GoodsReduceVO> goodsReduceList = BeanUtil.copyToList(fullReduceList, GoodsReduceVO.class);
            for (GoodsReduceVO goodsReduce : goodsReduceList) {
                if(ActivityEnum.FullReduceType.Coupon.name().equals(goodsReduce.getType())){
                    Coupons coupons = couponsService.getEntity(goodsReduce.getActivityCouponsId());
                    GoodsCouponsVO goodsCoupons = BeanUtil.toBean(coupons, GoodsCouponsVO.class);
                    if(null != coupons && CouponsEnum.Type.Gift.name().equals(coupons.getType())){//赠品券读取商品列表
                        List<GoodsVO> goodsList = couponsService.getViewModelList("get_coupons_goods_list", GoodsVO.class,
                                new Object[]{coupons.getActivityCouponsId(),coupons.getComId()});
                        goodsCoupons.setGoods(goodsList);
                    }
                    goodsReduce.setCoupons(goodsCoupons);
                }else if(ActivityEnum.FullReduceType.Goods.name().equals(goodsReduce.getType())){
                    FullReduceGiftGoodsVO goods = couponsService.getViewModel("get_goods_and_option",
                            FullReduceGiftGoodsVO.class, new Object[]{goodsReduce.getShopGoodsId(),goodsReduce.getShopGoodsOptionId(),goodsReduce.getComId()});
                    goods.setGiftNum(getGoodsFullReduceGiftNum(activity.getMarketActivityId(), goodsReduce.getShopGoodsId()));
                    goodsReduce.setGoods(goods);
                }
            }
            activity.setReduces(goodsReduceList.stream().sorted(Comparator.comparing(GoodsReduceVO::getFullPrice))
                    .collect(Collectors.toList()));
            return activity;
        }

        List<ActivityGoodsOptionVO> activityOptionsList = activityService.getViewModelList("get_activity_goods_option_list", ActivityGoodsOptionVO.class,
                new String[]{activity.getMarketActivityGoodsId(),activity.getComId()});
        int totalActivityStock = activityOptionsList.stream().mapToInt(item -> item.getActivityStock()).sum();

        if(totalActivityStock < 0){
            return null;
        }

        activity.setTotalActivityStock(totalActivityStock);
        activity.setOptionList(activityOptionsList);
        activity.setOrderNum(getActivityGoodsOrderUser(activity.getMarketActivityGoodsId()));

        //活动数据
        switch (ActivityEnum.Type.valueOf(activity.getType())){
            case Seckill:
                SeckillTimes seckillTimes = seckillTimesService.getEntity(activity.getMarketSeckillTimesId());

                String startTime = DateUtil.format(activity.getBeginDate(), DatePattern.NORM_DATE_PATTERN) + " " + seckillTimes.getStartTime() + ":00";
                String endTime = DateUtil.format(activity.getBeginDate(), DatePattern.NORM_DATE_PATTERN) + " " + seckillTimes.getEndTime() + ":00";
                DateTime now = DateUtil.date();

                //秒杀活动判断场次
                if(DateUtil.compare(DateUtil.parse(endTime),now) < 0 || DateUtil.compare(now,DateUtil.parse(startTime)) < 0){
                    return null;
                }

                activity.setSeckillTimes(BeanUtil.toBean(seckillTimes, SeckillTimesVO.class));
                break;

            case Group:
                List<Group> groupList = groupService.getList(new String[]{"status","market_activity_goods_id"},
                        new Object[]{OrderEnum.GroupStatus.Unopen.name(),activity.getMarketActivityGoodsId()});
                List<GoodsGroupVO> returnGroupList = BeanUtil.copyToList(groupList, GoodsGroupVO.class);

                for(GoodsGroupVO group : returnGroupList){

                    // 待成团列表
                    List<GroupOrderItemVO> groupOrderList = activityService.getViewModelList("get_effective_group_order_list",
                            GroupOrderItemVO.class, new Object[]{group.getMarketGroupId(),group.getComId()});
                    boolean isJoinGroup = groupOrderList.stream().anyMatch(item -> item.getMemberUserId().equals(userService.get().getMemberUserId()));
                    group.setUsers(groupOrderList);
                    group.setIsJoinGroup(isJoinGroup);
                }
                activity.setGroups(returnGroupList.stream().filter(item -> item.getGroupNum() > item.getUsers().size())
                        .collect(Collectors.toList()));
                break;

        }

        return activity;
    }
}
